import numpy as np
import pandas as pd
import feather
import os
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator

#建立历史数据表
def build_history_data(SampleTarget):
    '''
    建立历史数据表
    :param SampleTarget: 目标持仓表
    :return: 历史数据表
    '''
    history_data = feather.read_dataframe('1m/a.ft')
    history_data = history_data[history_data['timestamp'] == 145900]
    history_data = history_data[['trading_day']]
    start_day = SampleTarget['trading_day'][0]
#将目标持仓表中包含的品种历史数据收集到history_data中
    for filename in SampleTarget.columns[2:]:
        path = '1m/' + filename + '.ft'
        df = feather.read_dataframe(path)
        df = df[df['timestamp'] == 145900]
        df = df[['trading_day', 'clz']]
        df.columns = ['trading_day', filename]
        history_data = history_data.merge(df, how='left', on='trading_day')
        history_data = history_data[history_data['trading_day'] >= start_day]
#使用ffill向前填充，对Nan进行处理
    history_data.fillna(method='ffill', axis=0)
    history_data.fillna(0)
    return history_data
#计算某一品种的pnl值，并画出图像
def cul_pnl(pnl, name):
    '''
    用于计算某一品种的pnl值,并画出图像
    :param pnl: 全品种的每日pnl数据
    :param name: 对应品种的名字
    :return: 单一品种的累计pnl
    '''
    cur_pnl = pnl[name]
    cum_pnl = cur_pnl.cumsum()
    plt.plot(cum_pnl)
    return cum_pnl

def cul_total_pnl(history_data, SampleTarget):
    '''
    计算全品类的pnl
    :param history_data: 历史数据
    :param SampleTarget: 目标持仓表
    :return: 总pnl矩阵
    '''
    #计算相应期货价格的变化率
    chg = (history_data.shift(-1) - history_data)/history_data
    #用变化率乘持仓得到pnl值
    pnl = chg[chg.columns[1:]] * SampleTarget[SampleTarget.columns[2:]]
    return pnl.iloc[:SampleTarget.shape[0]]

def cul_sharp(pnl):
    '''
    计算夏普值
    :param pnl: 总的日pnl矩阵
    :return: sharp
    '''

    #
    new_pnl = pnl.sum(axis=1)
    sharp = np.mean(new_pnl) / np.std(new_pnl) * 15.8
    return sharp

def cul_turnover(history_data, SampleTarget):
    '''
    计算每天的成交金额
    :param history_data:
    :param SampleTarget:
    :return: 日成交金额
    '''
    chg = (history_data.shift(-1) - history_data)/history_data
    # 使用持仓价值 - 目标持仓的价值得到日换手金额
    turnover = (chg + 1)[chg.columns[1:]] * SampleTarget[SampleTarget.columns[2:]] - SampleTarget.shift(-1)[SampleTarget.columns[2:]]
    #减去手续费
    turnover = turnover - abs(turnover)*0.0003
    #计算全部品种的日换手金额
    turnover = turnover.sum(axis=1)
    return turnover.iloc[:SampleTarget.shape[0]]

def cul_AvgLeverage(SampleTarget, initmount):
    '''

    :param SampleTarget:
    :param initmount:
    :return:
    '''
    AvgLeverage = SampleTarget[SampleTarget.columns[2:]].sum(axis=1)
    AvgLeverage = AvgLeverage[len(AvgLeverage)-1] / initmount
    return AvgLeverage


if __name__ == "__main__":
    # 获取目标仓位表
    SampleTarget = pd.read_csv('SampleTarget1.csv')
    SampleTarget.fillna(method='ffill', axis=0)
    SampleTarget.fillna(0)

    # 判断初始金额
    if max(SampleTarget[SampleTarget.columns[2:]].iloc[0]) < 100:
        InitMount = 1
    else:
        InitMount = 1000000


    #获取历史数据
    history_data = build_history_data(SampleTarget)

    #pnl的累计量用于画图
    pnl = cul_total_pnl(history_data, SampleTarget)
    pnl_cum = pnl.sum(axis=1).cumsum()

    #计算turnover的累计值用于画图
    turnover = cul_turnover(history_data, SampleTarget)
    turnover_cum = turnover.cumsum()

    #计算总TurnOver
    TurnOver = turnover_cum[len(turnover) - 1] / InitMount

    #计算sharp值
    sharp = cul_sharp(pnl)

    #计算AvgLeverage
    AvgLeverage = cul_AvgLeverage(SampleTarget, InitMount)

    #绘制图像
    data = list(SampleTarget['trading_day'].astype('str'))
    plt.figure(figsize=(12,4))
    plt.plot(data, pnl_cum, 'r-', label='pnl')
    plt.plot(data, turnover_cum, 'b-', label='turnover')
    x_major_locator = MultipleLocator(500)
    ax = plt.gca()
    ax.xaxis.set_major_locator(x_major_locator)
    plt.legend()
    plt.title("Sharp=%f" %sharp + '  TurnOver=%f'%TurnOver + '  AvgLeverage=%f' %AvgLeverage)

